# -*- encoding:utf-8 -*-

from threading import Thread, RLock
from Queue import Queue
import time
import re
from log.LoggingRecord import LogRec
import sys
import traceback
from config.Config import Config
import constant.constant_define as constant_define
from service.base.TimeScan import TimeScan
from utils.SafeList import SafeList
import domain.Command as cmd
import datetime

class Fetcher(object):
    __rep_rules = [' ',  '&nbsp;', "&", 'id=', 'sina_keyword_ad_area2', 'articalContentnewfont_family', 'quote_','stock_','"thread_content">']

    __stock_tag = {
        re.compile(r"600\d{3}"),
        re.compile(r"601\d{3}"),
        re.compile(r"603\d{3}"),
        re.compile(r"300\d{3}"),
        re.compile(r"000\d{3}"),
        re.compile(r"002\d{3}"),
    }

    __regex_rules = {
        re.compile(r'''<[\s\S]+?>'''): "",
        re.compile(r"<!--[\s\S]+?--"): "",
        re.compile(r'''wt_article_link"onmouseover="WeiboCard.show\([\s\S]+?,'finance',this\)'''): "",
        re.compile(r'''"_baidu_bookmark[\s\S]+?"'''): "",
        re.compile(r'''\s+?'''): "",
    }

    __headers = constant_define.headers

    __proxies = {
        'http': 'http://127.0.0.1:8087',
        'https': 'http://127.0.0.1:8087',
    }

    def __init__(self, threads=0,timeout=60):
        self.__lock = RLock()
        self.__q_task = Queue()  # 任务队列  ， 存放要解决的任务的参数
        self.__q_complete = Queue()  # 完成队列  ，  存放需要获得的信息
        self.__q_running = SafeList() # 運行中的任务
        self.__threads = threads  # 线程数量
        self.__req_id = 0  # 处理中的任务id
        for i in xrange(threads):
            t = Thread(target=self.__threadget)
            t.setDaemon(True)  # 设置守护进程，即主进程关闭后，子进程也强制关闭
            t.start()
        #超时检测
        scan = TimeScan(timeout=timeout,q_running=self.__q_running)
        scan.setDaemon(True)
        scan.start()


    # 析构时等待两个队列完成
    def __del__(self):
        # join等到队列为null
        self.__q_task.join()
        # 再往__q_task添加不执行就可以，不用考虑阻止添加
        while self.__q_running.size()>0:
            time.sleep(0.5)
        self.__q_complete.join()

    # 剩余的任务线程
    def task_left(self):
        # 待完成的   +  已完成的  +  正在执行的
        return self.__q_task.qsize() + self.__q_complete.qsize() + self.__q_running.size()

    def push(self, req):
        self.__q_task.put(req)

    def pop(self):
        res = False
        try:
            res = self.__q_complete.get(True,2) #默认等待2秒
            self.__q_complete.task_done()  # 用于唤醒__q_complete.join()
        except Exception:
            res = False
        return res

    def __threadget(self):
        while True:
            # 默认block=True代表为阻塞式的，表示queue为空时，会等待
            req = self.__q_task.get()

            self.__lock.acquire()
            cmd_id = self.__req_id
            self.__q_running.append(cmd.create_cmd(cmd_id,req,datetime.datetime.now().second))
            self.__req_id += 1
            self.__lock.release()

            try:
                # 执行 具体任务
                # pass
                complete = self.__do_execute(req)

                self.__q_complete.put(complete)
            except Exception, e:
                info = sys.exc_info()
                err_logger = LogRec.get_logger(Config.ERRLOGGER)
                for file, lineno, function, text in traceback.extract_tb(info[2]):
                    err_str = file, "line:", lineno, "in", function
                    err_logger.error(err_str)
                err_str = "** %s: %s" % info[:2]
                err_logger.error(err_str)
                raise Exception(err_str)
            finally:
                self.__q_running.remove_by_id(cmd_id)

            # task_done 每次完成任务会递减任务数量，直到队列为空，从而唤醒queue.join(),使用get()无法唤醒
            self.__q_task.task_done()

            time.sleep(0.5)

    def __do_execute(self,req):
        # 避免频繁访问
        time.sleep(0.5)
        return self.do_work(req)

    # 具体业务逻辑
    # @abstractmethod   python3才支持
    def do_work(self,req):
        raise Exception('no implement exception', 'do_main method need implement')

    def get_replace_rules(self):
        return self.__rep_rules

    def get_regex_rules(self):
        return self.__regex_rules

    def get_stock_tag(self):
        return self.__stock_tag

    def get_headers(self):
        return self.__headers

    def set_headers(self):
        self.__headers

    def get_proxies(self):
        return self.__proxies
